package com;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Cylinder;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class ThirdPersonGame extends Application {

    private static final int WIDTH = 1280;
    private static final int HEIGHT = 720;

    // 场景元素
    private Group root = new Group();
    private Scene scene;
    private PerspectiveCamera camera = new PerspectiveCamera(true);

    // 角色相关
    private Group character;
    private double characterSpeed = 5.0;
    private double rotationSpeed = 2.0;
    private double cameraDistance = 300; // 摄像机与角色距离

    // 输入控制
    private boolean wPressed, sPressed, aPressed, dPressed;
    private double mouseX, mouseY;
    private double cameraAngleX = 15; // 初始俯角
    private double cameraAngleY = 0;

    @Override
    public void start(Stage primaryStage) {
        setupScene();
        createCharacter();
        setupCamera();
        setupControls();

        primaryStage.setTitle("第三人称角色演示");
        primaryStage.setScene(scene);
        primaryStage.show();

        startGameLoop();
    }

    // 初始化场景
    private void setupScene() {
        scene = new Scene(root, WIDTH, HEIGHT, true);
        scene.setFill(Color.SKYBLUE);
        scene.setCamera(camera);
    }

    // 配置摄像机
    private void setupCamera() {
        camera.setNearClip(0.1);
        camera.setFarClip(10000);

        // 初始视角参数调整
        cameraDistance = 150;     // ⭐ 缩短初始距离
        cameraAngleX = 30;        // ⭐ 调整俯角
        cameraAngleY = 45;        // ⭐ 初始水平角度
        // 确保角色已创建后再设置初始摄像机位置
        if (character != null) {
            updateCameraPosition();// 初始化摄像机位置
        }
    }

    // 创建角色模型
    private void createCharacter() {
        character = new Group();

        // 身体（长方体）
        Box body = new Box(30, 60, 20);
        body.setMaterial(new PhongMaterial(Color.BLUE));
        body.setTranslateY(-30); // 底部对齐

        // 头部（球体）
        Sphere head = new Sphere(15);
        head.setTranslateY(-60); // 位于身体上方
        head.setMaterial(new PhongMaterial(Color.PEACHPUFF));

        // 腿（圆柱体）
        Cylinder leftLeg = createLimb(-10, 20, Color.DARKBLUE);
        Cylinder rightLeg = createLimb(10, 20, Color.DARKBLUE);

        // 手臂
        Cylinder leftArm = createLimb(-25, -15, Color.LIGHTBLUE);
        Cylinder rightArm = createLimb(25, -15, Color.LIGHTBLUE);

        character.getChildren().addAll(body, head, leftLeg, rightLeg, leftArm, rightArm);
        root.getChildren().add(character);

        // 添加坐标系参考（调试用）
        addDebugAxes();
        // 显示碰撞体积（调试用）
        Box boundingBox = new Box(40, 80, 30);
        boundingBox.setMaterial(new PhongMaterial(Color.color(1, 0, 0, 0.2)));
        boundingBox.setTranslateY(-30);
        character.getChildren().add(boundingBox);
    }

    private void addDebugAxes() {
        // X轴（红色）
        Box xAxis = new Box(500, 2, 2);
        xAxis.setMaterial(new PhongMaterial(Color.RED));

        // Y轴（绿色）
        Box yAxis = new Box(2, 500, 2);
        yAxis.setMaterial(new PhongMaterial(Color.GREEN));

        // Z轴（蓝色）
        Box zAxis = new Box(2, 2, 500);
        zAxis.setMaterial(new PhongMaterial(Color.BLUE));

        root.getChildren().addAll(xAxis, yAxis, zAxis);
    }



    // 创建圆柱体肢体
    private Cylinder createLimb(double x, double y, Color color) {
        Cylinder limb = new Cylinder(5, 40);
        limb.setRotate(90); // 水平放置
        limb.setTranslateX(x);
        limb.setTranslateY(y);
        limb.setMaterial(new PhongMaterial(color));
        return limb;
    }

    // 设置输入控制
    private void setupControls() {
        // 键盘控制
        // 根据按下的键设置对应的控制标志
        scene.setOnKeyPressed(e -> {
            switch (e.getCode()) {
                case W: wPressed = true; break;
                case S: sPressed = true; break;
                case A: aPressed = true; break;
                case D: dPressed = true; break;
            }
        });

        // 注册键盘释放事件监听器
        scene.setOnKeyReleased(e -> {
            switch (e.getCode()) {
                case W: wPressed = false; break;
                case S: sPressed = false; break;
                case A: aPressed = false; break;
                case D: dPressed = false; break;
            }
        });

        // 鼠标控制视角
        // 注册鼠标移动事件监听器
        scene.setOnMouseMoved(e -> {
            // 计算鼠标移动增量
            // 计算当前帧与上一帧的鼠标位置差值（增量）
            // deltaX: 水平方向移动量（左右移动）
            double deltaX = e.getSceneX() - mouseX;
            // deltaY: 垂直方向移动量（上下移动）
            double deltaY = e.getSceneY() - mouseY;

            // 调整摄像机角度
            cameraAngleY += deltaX * 0.05;
            cameraAngleX = Math.max(10, Math.min(80, cameraAngleX + deltaY * 0.05));

            // 保存当前鼠标位置
            mouseX = e.getSceneX();
            mouseY = e.getSceneY();

            updateCameraPosition();
        });
    }

    // 更新摄像机位置
    private void updateCameraPosition() {
        // 计算球坐标位置
        double theta = Math.toRadians(cameraAngleY);
        double phi = Math.toRadians(cameraAngleX);

        double offsetX = cameraDistance * Math.sin(theta) * Math.cos(phi);
        double offsetY = cameraDistance * Math.sin(phi);
        double offsetZ = cameraDistance * Math.cos(theta) * Math.cos(phi);

        // 摄像机最终位置 = 角色位置 + 球坐标偏移
        camera.getTransforms().clear();
        camera.getTransforms().addAll(
                new Translate( // ⭐ 修正坐标计算顺序
                        character.getTranslateX() - offsetX,
                        character.getTranslateY() - offsetY + 50, // +50保持俯视高度
                        character.getTranslateZ() - offsetZ
                )
        );

        camera.setRotationAxis(Rotate.Y_AXIS);
        camera.setRotate(-cameraAngleY);
    }

    // 游戏主循环
    private void startGameLoop() {
        new AnimationTimer() {
            @Override
            public void handle(long now) {
                handleMovement();
                updateCameraPosition();

                // 打印调试信息
                System.out.printf("角色位置: (%.1f, %.1f, %.1f)%n",
                        character.getTranslateX(),
                        character.getTranslateY(),
                        character.getTranslateZ());
                System.out.printf("摄像机位置: (%.1f, %.1f, %.1f)%n",
                        camera.getTranslateX(),
                        camera.getTranslateY(),
                        camera.getTranslateZ());
            }
        }.start();
    }

    // 处理角色移动
    private void handleMovement() {
        // 计算前进方向（基于摄像机角度）
        double radian = Math.toRadians(cameraAngleY);
        double forwardX = Math.sin(radian);
        double forwardZ = Math.cos(radian);

        // 计算移动向量
        double moveX = 0, moveZ = 0;

        if (wPressed) {
            moveX += forwardX;
            moveZ += forwardZ;
        }
        if (sPressed) {
            moveX -= forwardX;
            moveZ -= forwardZ;
        }
        if (aPressed) {
            moveX += forwardZ;
            moveZ -= forwardX;
        }
        if (dPressed) {
            moveX -= forwardZ;
            moveZ += forwardX;
        }

        // 标准化移动向量
        double length = Math.sqrt(moveX*moveX + moveZ*moveZ);
        if (length > 0) {
            moveX = moveX / length * characterSpeed;
            moveZ = moveZ / length * characterSpeed;
        }

        // 更新角色位置
        character.setTranslateX(character.getTranslateX() + moveX);
        character.setTranslateZ(character.getTranslateZ() + moveZ);

        // 更新角色朝向
        if (length > 0) {
            double targetAngle = Math.toDegrees(Math.atan2(moveX, moveZ));
            character.setRotate(targetAngle);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}